﻿using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Data;
using System.Windows.Forms;
using System.Drawing;
using System.Reflection;
using THSLib;
using THSERP.BusinessEntities;
using DevExpress.XtraTreeList;
using DevExpress.XtraTreeList.Nodes;

namespace THSERP.BaseProvider
{
    public partial class THSTreeListControl: DevExpress.XtraTreeList.TreeList
    {
        #region Variables
        protected THSERPScreen _screen;
        protected String _THSFieldGroup;
        protected String _THSDataSource;
        protected String _THSComment;
        protected String _THSError;
        protected bool _THSDisplayRoot;
        protected bool _THSDisplayOption;
        protected String _THSPrivilege;
        public TreeListHitInfo SourceHitInfo;
        #endregion

        #region Public properties
        public THSERPScreen Screen
        {
            get
            {
                return _screen;
            }
            set
            {
                _screen = value;
            }
        }

        [Category("THS")]
        public bool THSDisplayRoot
        {
            get
            {
                return _THSDisplayRoot;
            }
            set
            {
                _THSDisplayRoot = value;
            }
        }

        [Category("THS")]
        public bool THSDisplayOption
        {
            get
            {
                return _THSDisplayOption;
            }
            set
            {
                _THSDisplayOption = value;
            }
        }

        [Category("THS")]
        public String THSFieldGroup
        {
            get
            {
                return _THSFieldGroup;
            }
            set
            {
                _THSFieldGroup = value;
            }
        }

        [Category("THS")]
        public String THSDataSource
        {
            get
            {
                return _THSDataSource;
            }
            set
            {
                _THSDataSource = value;
            }
        }

        [Category("THS")]
        public String THSComment
        {
            get
            {
                return _THSComment;
            }
            set
            {
                _THSComment = value;
            }
        }

        [Category("THS")]
        public String THSError
        {
            get
            {
                return _THSError;
            }
            set
            {
                _THSError = value;
            }
        }

        [Category("THS")]
        public String THSPrivilege
        {
            get
            {
                return _THSPrivilege;
            }
            set
            {
                _THSPrivilege = value;
            }
        }
        #endregion

        public THSTreeListControl()
        {
            InitializeComponent();
        }

        public THSTreeListControl(IContainer container)
        {
            container.Add(this);

            InitializeComponent();
        }

        public virtual void InitializeControl()
        {
            //Init tree list columns
            InitTreeListColumns(THSDataSource);

            //Init tree list data source
            InitTreeListDataSource();
            //
            this.KeyUp += new KeyEventHandler(THSTreeListControl_KeyUp);
            this.NodeCellStyle += new DevExpress.XtraTreeList.GetCustomNodeCellStyleEventHandler(THSTreeListControl_NodeCellStyle);
            this.FocusedNodeChanged += new DevExpress.XtraTreeList.FocusedNodeChangedEventHandler(THSTreeListControl_FocusedNodeChanged);
            this.MouseMove += new MouseEventHandler(THSTreeListControl_MouseMove);
            this.MouseDown += new MouseEventHandler(THSTreeListControl_MouseDown);
            this.DragOver += new DragEventHandler(THSTreeListControl_DragOver);
            this.DragDrop += new DragEventHandler(THSTreeListControl_DragDrop);
        }
       
      
        public virtual void InitTreeListColumns(String strTableName)
        {
            //Add bound columns
            AAColumnAliasController objAAColumnAliasController = new AAColumnAliasController();
            DataSet dsColumns = objAAColumnAliasController.GetAAColumnAliasByTableName(strTableName);
            if (dsColumns.Tables.Count > 0)
            {
                int index = 0;
                foreach (DataRow rowColumn in dsColumns.Tables[0].Rows)
                {
                    AAColumnAliasInfo objAAColumnAliasInfo = (AAColumnAliasInfo)objAAColumnAliasController.GetObjectFromDataRow(rowColumn);
                    if (objAAColumnAliasInfo != null)
                    {
                        if (this.Columns.ColumnByFieldName(objAAColumnAliasInfo.AAColumnAliasName) == null)
                        {
                            DevExpress.XtraTreeList.Columns.TreeListColumn column = InitTreeListColumn(strTableName, index, objAAColumnAliasInfo.AAColumnAliasName, objAAColumnAliasInfo.AAColumnAliasCaption, 50);
                            if (THSDbUtil.IsForeignKey(strTableName, objAAColumnAliasInfo.AAColumnAliasName))
                            {
                                DevExpress.XtraEditors.Repository.RepositoryItemLookUpEdit repLookupEdit = InitColumnLookupEdit(strTableName, objAAColumnAliasInfo.AAColumnAliasName);
                                if (repLookupEdit != null)
                                {
                                    column.ColumnEdit = repLookupEdit;
                                    this.RepositoryItems.Add(repLookupEdit);
                                }
                            }
                            else
                            {
                                String strConfigValueTable = String.Empty;

                                if (objAAColumnAliasInfo.AAColumnAliasName.EndsWith("Combo"))
                                    strConfigValueTable = objAAColumnAliasInfo.AAColumnAliasName.Substring(2, objAAColumnAliasInfo.AAColumnAliasName.Length - 7);
                                else
                                    strConfigValueTable = objAAColumnAliasInfo.AAColumnAliasName.Substring(2, objAAColumnAliasInfo.AAColumnAliasName.Length - 2);

                                if (ADConfigValueUtility.glbdsConfigValues.Tables[strConfigValueTable] != null)
                                {
                                    DevExpress.XtraEditors.Repository.RepositoryItemLookUpEdit repLookupEdit = new DevExpress.XtraEditors.Repository.RepositoryItemLookUpEdit();

                                    repLookupEdit.DataSource = ADConfigValueUtility.glbdsConfigValues.Tables[strConfigValueTable];
                                    repLookupEdit.ValueMember = "Value";
                                    repLookupEdit.DisplayMember = "Text";
                                    DevExpress.XtraEditors.Controls.LookUpColumnInfo repColumn = new DevExpress.XtraEditors.Controls.LookUpColumnInfo();
                                    repColumn.FieldName = "Text";
                                    repColumn.Width = 100;
                                    repLookupEdit.Columns.Add(repColumn);
                                    repLookupEdit.PopupWidth = repColumn.Width;
                                    column.ColumnEdit = repLookupEdit;
                                    this.RepositoryItems.Add(repLookupEdit);
                                }
                                else
                                {
                                    //Init column repository based on field format group
                                    DevExpress.XtraEditors.Repository.RepositoryItem repItem = InitColumnRepositoryFromFieldFormatGroup(strTableName, objAAColumnAliasInfo.AAColumnAliasName);
                                    column.ColumnEdit = repItem;
                                    this.RepositoryItems.Add(repItem);
                                }
                            }

                            if (column.ColumnEdit != null)
                                InitColumnRepositoryFormat(column, strTableName, objAAColumnAliasInfo.AAColumnAliasName);
                            else
                                InitColumnFormat(column, strTableName, objAAColumnAliasInfo.AAColumnAliasName);

                            column.OptionsColumn.AllowEdit = false;
                            this.Columns.AddRange(new DevExpress.XtraTreeList.Columns.TreeListColumn[] { column });
                            index++;
                        }
                        else
                        {
                            this.Columns[objAAColumnAliasInfo.AAColumnAliasName].Caption = objAAColumnAliasInfo.AAColumnAliasCaption;
                        }
                    }
                }
            }

            if (THSDisplayOption)
            {
                DevExpress.XtraTreeList.Columns.TreeListColumn column = InitTreeListColumn(strTableName, this.Columns.Count, "Selected", "Chọn", 5);
                column.ColumnEdit = new DevExpress.XtraEditors.Repository.RepositoryItemCheckEdit();
                this.Columns.AddRange(new DevExpress.XtraTreeList.Columns.TreeListColumn[] { column });
                this.RepositoryItems.Add(column.ColumnEdit);
            }
        }

        protected virtual DevExpress.XtraTreeList.Columns.TreeListColumn InitTreeListColumn(String strTableName, int iVisibleIndex, String strFieldName, String strCaption, int iWidth)
        {
            DevExpress.XtraTreeList.Columns.TreeListColumn column = new DevExpress.XtraTreeList.Columns.TreeListColumn();
            column.Name = "col" + strFieldName;
            column.Caption = strCaption;
            column.FieldName = strFieldName;
            column.VisibleIndex = iVisibleIndex;
            column.Visible = true;
            column.Width = iWidth;
            return column;
        }

        protected virtual DevExpress.XtraEditors.Repository.RepositoryItemLookUpEdit InitColumnLookupEdit(String strTableName, String strColumnName)
        {
            DevExpress.XtraEditors.Repository.RepositoryItemLookUpEdit rep = new DevExpress.XtraEditors.Repository.RepositoryItemLookUpEdit();
            rep.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.Standard;
            rep.SearchMode = DevExpress.XtraEditors.Controls.SearchMode.AutoFilter;
            rep.NullText = String.Empty;

            String strLookupTable = THSDbUtil.GetPrimaryTableWhichForeignColumnReferenceTo(strTableName, strColumnName);
            if (THSApp.LookupTables[strLookupTable] == null)
                return null;
           
            rep.DataSource =  ((DataSet)THSApp.LookupTables[strLookupTable]).Tables[0];
            String strPrimaryColumn = THSDbUtil.GetTablePrimaryColumn(strLookupTable);
            String strDisplayColumn = GetLookupTableDisplayColumn(strLookupTable);
            rep.ValueMember = strPrimaryColumn;
            rep.DisplayMember = strDisplayColumn;

            rep.QueryPopUp += new CancelEventHandler(RepositoryItemLookupEdit_QueryPopup);

            DevExpress.XtraEditors.Controls.LookUpColumnInfo colName = new DevExpress.XtraEditors.Controls.LookUpColumnInfo();
            colName.FieldName = strDisplayColumn;
            colName.Caption = strDisplayColumn.Substring(strPrimaryColumn.Length - 2);
            colName.Width = 100;

            rep.Columns.Add(colName);

            return rep;
        }

        protected virtual String GetLookupTableDisplayColumn(String strLookupTableName)
        {
           
            String strPrimaryColumn = THSDbUtil.GetTablePrimaryColumn(strLookupTableName);
            String prefix = strPrimaryColumn.Substring(0, strPrimaryColumn.Length - 2);
            if (THSDbUtil.ColumnIsExist(strLookupTableName, prefix + "No"))
                return prefix + "No";
            else if (THSDbUtil.ColumnIsExist(strLookupTableName, prefix + "Name"))
                return prefix + "Name";
            return String.Empty;
        }

        

        protected virtual DevExpress.XtraEditors.Repository.RepositoryItem InitColumnRepositoryFromFieldFormatGroup(String strTableName, String strColumnName)
        {
            STFieldFormatGroupsController objFieldFormatGroupsController = new STFieldFormatGroupsController();
            STFieldFormatGroupsInfo objFieldFormatGroupsInfo = objFieldFormatGroupsController.GetFieldFormatGroupByModuleNameAndTableNameAndColumnName(this.Screen.Module.Name, strTableName, strColumnName);
            if (objFieldFormatGroupsInfo != null)
            {
                if (!String.IsNullOrEmpty(objFieldFormatGroupsInfo.STFieldFormatGroupRepository))
                {
                    return THSUtil.GetRepositoryItemFromText(objFieldFormatGroupsInfo.STFieldFormatGroupRepository);
                }
            }
            return null;
        }

        protected virtual void InitColumnRepositoryFormat(DevExpress.XtraTreeList.Columns.TreeListColumn column, String strTableName, String strColumnName)
        {
            STFieldFormatGroupsController objFieldFormatGroupsController = new STFieldFormatGroupsController();
            STFieldFormatGroupsInfo objFieldFormatGroupsInfo = objFieldFormatGroupsController.GetFieldFormatGroupByModuleNameAndTableNameAndColumnName(this.Screen.Module.Name, strTableName, strColumnName);
            if (objFieldFormatGroupsInfo != null)
            {
                DevExpress.XtraEditors.Repository.RepositoryItem rep = column.ColumnEdit;
                if (objFieldFormatGroupsInfo.STFieldFormatGroupBackColor > 0)
                {
                    rep.Appearance.BackColor = Color.FromArgb(objFieldFormatGroupsInfo.STFieldFormatGroupBackColor);
                    rep.Appearance.Options.UseBackColor = true;
                }
                if (objFieldFormatGroupsInfo.STFieldFormatGroupForeColor > 0)
                {
                    rep.Appearance.ForeColor = Color.FromArgb(objFieldFormatGroupsInfo.STFieldFormatGroupForeColor);
                    rep.Appearance.Options.UseForeColor = true;
                }

                String strDefaultFontName = "Tahoma";
                float fDefaultFontSize = 8.25F;
                if (!String.IsNullOrEmpty(objFieldFormatGroupsInfo.STFieldFormatGroupFontName))
                    strDefaultFontName = objFieldFormatGroupsInfo.STFieldFormatGroupFontName;
                if (objFieldFormatGroupsInfo.STFieldFormatGroupFontSize > 0)
                    fDefaultFontSize = objFieldFormatGroupsInfo.STFieldFormatGroupFontSize;
                rep.Appearance.Font = new Font(strDefaultFontName, fDefaultFontSize);
                rep.Appearance.Options.UseFont = true;

                if (THSUtil.IsEditRepository(rep))
                {
                    DevExpress.XtraEditors.Repository.RepositoryItemTextEdit repText = (DevExpress.XtraEditors.Repository.RepositoryItemTextEdit)rep;
                    if (objFieldFormatGroupsInfo.STFieldFormatGroupDecimalRound > 0)
                    {
                        repText.Mask.MaskType = DevExpress.XtraEditors.Mask.MaskType.Numeric;
                        repText.Mask.EditMask = String.Format("n{0}", objFieldFormatGroupsInfo.STFieldFormatGroupDecimalRound);
                        repText.Mask.UseMaskAsDisplayFormat = true;
                    }
                    else
                    {
                        if (!String.IsNullOrEmpty(objFieldFormatGroupsInfo.STFieldFormatGroupMaskType))
                        {
                            repText.Mask.MaskType = THSUtil.GetMaskTypeFromText(objFieldFormatGroupsInfo.STFieldFormatGroupMaskType);
                            repText.Mask.EditMask = objFieldFormatGroupsInfo.STFieldFormatGroupMaskEdit;
                            repText.Mask.UseMaskAsDisplayFormat = true;
                        }
                        if (!String.IsNullOrEmpty(objFieldFormatGroupsInfo.STFieldFormatGroupFormatType))
                        {
                            repText.DisplayFormat.FormatType = THSUtil.GetFormatTypeFromText(objFieldFormatGroupsInfo.STFieldFormatGroupFormatType);
                            repText.DisplayFormat.FormatString = objFieldFormatGroupsInfo.STFieldFormatGroupFormatString;
                        }
                    }
                }
            }
        }

        protected virtual void InitColumnFormat(DevExpress.XtraTreeList.Columns.TreeListColumn column, String strTableName, String strColumnName)
        {
            STFieldFormatGroupsController objFieldFormatGroupsController = new STFieldFormatGroupsController();
            STFieldFormatGroupsInfo objFieldFormatGroupsInfo = objFieldFormatGroupsController.GetFieldFormatGroupByModuleNameAndTableNameAndColumnName(this.Screen.Module.Name, strTableName, strColumnName);
            if (objFieldFormatGroupsInfo != null)
            {
                if (objFieldFormatGroupsInfo.STFieldFormatGroupBackColor > 0)
                {
                    column.AppearanceCell.BackColor = Color.FromArgb(objFieldFormatGroupsInfo.STFieldFormatGroupBackColor);
                    column.AppearanceCell.Options.UseBackColor = true;
                }
                if (objFieldFormatGroupsInfo.STFieldFormatGroupForeColor > 0)
                {
                    column.AppearanceCell.ForeColor = Color.FromArgb(objFieldFormatGroupsInfo.STFieldFormatGroupForeColor);
                    column.AppearanceCell.Options.UseForeColor = true;
                }

                String strDefaultFontName = "Tahoma";
                float fDefaultFontSize = 8.25F;
                if (!String.IsNullOrEmpty(objFieldFormatGroupsInfo.STFieldFormatGroupFontName))
                    strDefaultFontName = objFieldFormatGroupsInfo.STFieldFormatGroupFontName;
                if (objFieldFormatGroupsInfo.STFieldFormatGroupFontSize > 0)
                    fDefaultFontSize = objFieldFormatGroupsInfo.STFieldFormatGroupFontSize;
                column.AppearanceCell.Font = new Font(strDefaultFontName, fDefaultFontSize);
                column.AppearanceCell.Options.UseFont = true;

                if (objFieldFormatGroupsInfo.STFieldFormatGroupDecimalRound > 0)
                {
                    column.ColumnEdit = THSUtil.GetRepositoryItemFromText("RepositoryItemTextEdit");
                    InitColumnRepositoryFormat(column, strTableName, strColumnName);
                }
            }
        }

        protected virtual void InitTreeListDataSource()
        {

        }

        public DevExpress.XtraTreeList.Nodes.TreeListNode GetSelectedNode()
        {
            if (this.FocusedNode != null)
                return this.FocusedNode;
            else if (THSDisplayRoot)
                return this.Nodes.FirstNode;
            else
                return null;
        }

        public static THSTreeListControl Instance(String strInstanceName, String strModuleName)
        {
            if (!String.IsNullOrEmpty(strInstanceName))
            {
                Type treeListType = THSApp.THSERPAssembly.GetType("THSERP.Modules." + strModuleName + "." + strInstanceName + "TreeListControl");
                if (treeListType != null)
                {
                    return (THSTreeListControl)treeListType.InvokeMember("", BindingFlags.CreateInstance, null, null, null);
                }
                else
                {
                    treeListType = THSApp.THSERPAssembly.GetType("THSERP." + strInstanceName + "TreeListControl");
                    if (treeListType != null)
                        return (THSTreeListControl)treeListType.InvokeMember("", BindingFlags.CreateInstance, null, null, null);
                    else
                        return new THSTreeListControl();
                }
            }
            else
                return new THSTreeListControl();
        }

        /// <summary>
        /// Invalidate lookup edit columns to reflect all changes of lookup table
        /// </summary>
        public virtual void InvalidateLookupEditColumns()
        {
            foreach (DevExpress.XtraTreeList.Columns.TreeListColumn column in this.Columns)
                if (column.ColumnEdit != null && column.ColumnEdit.GetType() == typeof(DevExpress.XtraEditors.Repository.RepositoryItemLookUpEdit))
                {
                   
                    DevExpress.XtraEditors.Repository.RepositoryItemLookUpEdit rep = (DevExpress.XtraEditors.Repository.RepositoryItemLookUpEdit)column.ColumnEdit;
                    String strLookupTable = THSDbUtil.GetPrimaryTableWhichForeignColumnReferenceTo(THSDataSource, column.FieldName);
                    //Update lookup table if there is any changes to it
                    DateTime dtLastCreatedDate = THSDbUtil.GetLastCreatedDateOfTable(strLookupTable);
                    DateTime dtLastUpdatedDate = THSDbUtil.GetLastUpdatedDateOfTable(strLookupTable);
                    if (dtLastCreatedDate.CompareTo(((DateTime)THSApp.LookupTablesUpdatedDate[strLookupTable])) > 0 ||
                        dtLastUpdatedDate.CompareTo(((DateTime)THSApp.LookupTablesUpdatedDate[strLookupTable])) > 0)
                    {
                        //Refesh Data Source
                        BaseBusinessController objLookupTableController = BusinessControllerFactory.GetBusinessController(strLookupTable + "Controller");
                        if (objLookupTableController != null)
                        {
                            DataSet ds = objLookupTableController.GetAllObjects();
                            if (ds.Tables.Count > 0)
                            {
                                // Update Last Updated Date of Lookup Table
                                THSApp.LookupTablesUpdatedDate[strLookupTable] = DateTime.Now;
                                ((DataSet)THSApp.LookupTables[strLookupTable]).Tables.Clear();
                                ((DataSet)THSApp.LookupTables[strLookupTable]).Tables.Add(ds.Tables[0].Copy());
                            }
                        }
                    }
                    rep.DataSource = ((DataSet)THSApp.LookupTables[strLookupTable]).Tables[0];
                }
        }
        #region--Event handler--
        protected virtual void TreeListControl_CellValueChanging(object sender, DevExpress.XtraTreeList.CellValueChangedEventArgs e)
        {
            
        }
         protected virtual void THSTreeListControl_KeyUp(object sender, KeyEventArgs e)
        {
            
        }
        protected virtual void THSTreeListControl_FocusedNodeChanged(object sender, DevExpress.XtraTreeList.FocusedNodeChangedEventArgs e)
        {
            
        }

        protected virtual  void THSTreeListControl_NodeCellStyle(object sender, DevExpress.XtraTreeList.GetCustomNodeCellStyleEventArgs e)
        {
            
        }
        protected virtual void RepositoryItemLookupEdit_QueryPopup(object sender, CancelEventArgs e)
        {

            DevExpress.XtraEditors.LookUpEdit lke = (DevExpress.XtraEditors.LookUpEdit)sender;
            String strLookupTable = lke.Properties.ValueMember.Substring(0, lke.Properties.ValueMember.Length - 2) + "s";
            DateTime dtLastCreatedDate = THSDbUtil.GetLastCreatedDateOfTable(strLookupTable);
            DateTime dtLastUpdatedDate = THSDbUtil.GetLastUpdatedDateOfTable(strLookupTable);

            if (dtLastCreatedDate.CompareTo(((DateTime)THSApp.LookupTablesUpdatedDate[strLookupTable])) > 0 ||
                dtLastUpdatedDate.CompareTo(((DateTime)THSApp.LookupTablesUpdatedDate[strLookupTable])) > 0)
            {
                //Refesh Data Source
                BaseBusinessController objLookupTableController = BusinessControllerFactory.GetBusinessController(strLookupTable + "Controller");
                if (objLookupTableController != null)
                {
                    DataSet ds = objLookupTableController.GetAllObjects();

                    if (ds.Tables.Count > 0)
                    {
                        BindingSource bds = new BindingSource();
                        bds.DataSource = ds.Tables[0];
                        lke.Properties.DataSource = bds;
                        bds.ResetBindings(false);

                        // Update Last Updated Date of Lookup Table
                        THSApp.LookupTablesUpdatedDate[strLookupTable] = DateTime.Now;
                        ((DataSet)THSApp.LookupTables[strLookupTable]).Tables.Clear();
                        ((DataSet)THSApp.LookupTables[strLookupTable]).Tables.Add(ds.Tables[0].Copy());
                    }
                }
            }
        }
        #region--do drag drop--

        private TreeListNode GetDragNode(IDataObject data)
        {
            return data.GetData(typeof(TreeListNode)) as TreeListNode;
        }
      public virtual  void THSTreeListControl_DragDrop(object sender, DragEventArgs e)
        {
            //throw new Exception("The method or operation is not implemented.");
        }

       public virtual void THSTreeListControl_DragOver(object sender, DragEventArgs e)
        {
            TreeListHitInfo hi = this.CalcHitInfo(this.PointToClient(new Point(e.X, e.Y)));
            TreeListNode node = GetDragNode(e.Data);
            if (node == null)
            {
                if (hi.HitInfoType == HitInfoType.Empty || hi.Node != null)
                    e.Effect = DragDropEffects.Move;
                else
                    e.Effect = DragDropEffects.None;
            }
        }

       public virtual void THSTreeListControl_MouseDown(object sender, MouseEventArgs e)
        {
            SourceHitInfo = null;
            TreeListHitInfo hitInfo = this.CalcHitInfo(new Point(e.X, e.Y));
            if (Control.ModifierKeys != Keys.None) return;
            if (e.Button == MouseButtons.Left)
                SourceHitInfo = hitInfo;
        }

       public virtual void THSTreeListControl_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left && SourceHitInfo != null)
            {
                Size dragSize = SystemInformation.DragSize;
                Rectangle dragRect = new Rectangle(new Point(SourceHitInfo.MousePoint.X - dragSize.Width / 2,
                    SourceHitInfo.MousePoint.Y - dragSize.Height / 2), dragSize);

                if (!dragRect.Contains(new Point(e.X, e.Y)))
                {
                    this.DoDragDrop(SourceHitInfo, DragDropEffects.All);
                    SourceHitInfo = null;
                }
            }
        }


        #endregion
        #endregion
    }
}
